﻿using Bandit.Helpers;
using ETC.DLEDLightingSystemPlus.Helpers;
using ETC.DLEDLightingSystemPlus.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;

namespace ETC.DLEDLightingSystemPlus
{
    public class TetraController
    {
        BanditSFtp _Sftp = null;

        private string _RootPath = "/";

        private const string _DeviceName = "pi";

        public string Name { get; set; }

        /// <summary>
        /// 主机地址
        /// </summary>
        public string Address { get; private set; }

        public Tetra Model { get; private set; }

        public TetraController(Tetra model)
        {
            this.Model = model;

            this.Address = model.Address;
            string username = "pi";//model.UserName;
            string password = model.Password;

            if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
            {
                username = "firefly";
                password = "firefly";
            }

            this._RootPath = "/home/pi/Jakey/";

            this._Sftp = new BanditSFtp(this.Address, username, password);
            this._Sftp.OnErrorOccurred += Sftp_OnErrorOccurred;
        }

        private void Sftp_OnErrorOccurred(object sender, Renci.SshNet.Common.ExceptionEventArgs e)
        {
            LogHelper.Error(e.Exception, "OnErrorOccurred");
            if (e.Exception is Renci.SshNet.Common.SshConnectionException ex)
            {
                this.Model.State = false;
            }
        }

        public bool Connect()
        {
            bool result = false;
            try
            {
                result = this._Sftp.Connect();
            }
            catch (Exception ex)
            {
                Console.WriteLine("ServerController.Connect : " + ex.Message);
            }

            this.Model.State = result;

            return this.Model.State;
        }

        public bool CleanPG()
        {
            return _Sftp.DeleteDirectory(this._RootPath);
        }

        #region 上传配置

        //public ResultState UploadConfig(Config config, Action onProgressChanged = null)
        //{
        //    var data = Models.ConfigData.LoadConfig(config.Path);

        //    if (data == null)
        //    {
        //        return ResultState.ConfigFileMiss;
        //    }

        //    #region Progress
        //    config.Progress = 0;
        //    double position = 0;
        //    int fileTotalCount = data.GetFileCount();

        //    void updateProgress()
        //    {
        //        position++;
        //        config.Progress = position / fileTotalCount;

        //        onProgressChanged?.Invoke();
        //    }
        //    #endregion

        //    if (data.Video != null)
        //    {
        //        if (!this.UploadFile(data.Video.RelativePath))
        //        {
        //            return ResultState.UploadVideoFileFail;
        //        }
        //        updateProgress();
        //    }

        //    if (data.IsCheckEDID && data.EDIDFile != null)
        //    {
        //        if (!this.UploadFile(data.EDIDFile.RelativePath))
        //        {
        //            return ResultState.UploadEDIDFileFail;
        //        }
        //        updateProgress();
        //    }

        //    foreach (var item in data.Patterns)
        //    {
        //        if (!this.UploadFile(item.RelativePath))
        //        {
        //            return ResultState.UploadPatternFileFail;
        //        }
        //        updateProgress();
        //    }

        //    if (!this.UploadFile(config.Path))
        //    {
        //        return ResultState.UploadConfigFileFail;
        //    }
        //    updateProgress();

        //    var model = this.DB.Configs.FirstOrDefault(s => s.IsEqual(data.Project, data.Station, data.Version));

        //    if (model != null)
        //    {
        //        this.DB.Configs.Remove(model);
        //    }

        //    this.DB.Configs.Add(config);

        //    return ResultState.OK;
        //}

        //public void UploadConfigs(List<Config> configs, Action<ProgressArgs> progressUpdate)
        //{
        //    progressUpdate.Invoke(new ProgressArgs(ProgressState.GroupStarted, null, -1));

        //    List<int> failedIndex = new List<int>();

        //    for (int i = 0; i < configs.Count; i++)
        //    {
        //        Config config = configs[i];

        //        progressUpdate.Invoke(new ProgressArgs(ProgressState.Started, config, i));

        //        ResultState resultState = this.UploadConfig(config, delegate
        //        {
        //            progressUpdate.Invoke(new ProgressArgs(ProgressState.UpdateProgress, config, i));
        //        });

        //        if (resultState != ResultState.OK)
        //        {
        //            failedIndex.Add(i);
        //        }

        //        progressUpdate.Invoke(new ProgressArgs(ProgressState.Finished, config, i, resultState));
        //    }

        //    this.SaveAndUpdateDB();

        //    progressUpdate.Invoke(new ProgressArgs(ProgressState.GroupFinished, null, -1, failedIndex.Count == 0 ? ResultState.OK : ResultState.UploadConfigFail) { Remark = string.Join(",", failedIndex) });
        //}

        #endregion

        #region 下载配置

        //public ResultState DownloadConfig(Config config, Action onProgressChanged = null)
        //{
        //    #region Progress
        //    config.Progress = 0;
        //    double position = 0;
        //    int fileTotalCount;
        //    void updateProgress()
        //    {
        //        position++;
        //        config.Progress = position / fileTotalCount;

        //        onProgressChanged?.Invoke();
        //    }
        //    #endregion

        //    if (!this.DownloadFile(config.Path))
        //    {
        //        return ResultState.DownloadConfigFileFail;
        //    }
        //    var data = Models.ConfigData.LoadConfig(this.GetBaseDirectory() + config.Path);
        //    fileTotalCount = data.GetFileCount();
        //    updateProgress();

        //    if (data.Video != null)
        //    {
        //        if (!this.DownloadFile(data.Video.RelativePath))
        //        {
        //            return ResultState.DownloadVideoFileFail;
        //        }
        //        updateProgress();
        //    }

        //    if (data.IsCheckEDID && data.EDIDFile != null)
        //    {
        //        if (!this.DownloadFile(data.EDIDFile.RelativePath))
        //        {
        //            return ResultState.DownloadEDIDFileFail;
        //        }
        //        updateProgress();
        //    }

        //    foreach (var item in data.Patterns)
        //    {
        //        if (!this.DownloadFile(item.RelativePath))
        //        {
        //            return ResultState.DownloadPatternFileFail;
        //        }
        //        updateProgress();
        //    }

        //    config.Data = data;

        //    return ResultState.OK;
        //}



        //public void DownloadConfigs(List<Config> configs, Action<ProgressArgs> progressUpdate)
        //{
        //    progressUpdate.Invoke(new ProgressArgs(ProgressState.GroupStarted, null, -1));

        //    List<int> failedIndex = new List<int>();

        //    for (int i = 0; i < configs.Count; i++)
        //    {
        //        Config config = configs[i];

        //        progressUpdate.Invoke(new ProgressArgs(ProgressState.Started, config, i));

        //        ResultState resultState = this.DownloadConfig(config, delegate
        //        {
        //            progressUpdate.Invoke(new ProgressArgs(ProgressState.UpdateProgress, config, i));
        //        });

        //        if (resultState != ResultState.OK)
        //        {
        //            failedIndex.Add(i);
        //        }

        //        progressUpdate.Invoke(new ProgressArgs(ProgressState.Finished, config, i, resultState));
        //    }

        //    progressUpdate.Invoke(new ProgressArgs(ProgressState.GroupFinished, null, -1, failedIndex.Count == 0 ? ResultState.OK : ResultState.DownloadConfigFail) { Remark = string.Join(",", failedIndex) });
        //}

        #endregion

        #region 删除配置

        //public void Delete(Config item)
        //{
        //    string remotePath = Path.GetDirectoryName(string.Format("{0}{1}", _RootPath, item.Path)).Replace("\\", "/");

        //    if (_Sftp.DeleteDirectory(remotePath))
        //    {
        //        this.DeleteParentDir(remotePath);
        //    }
        //}

        //private void DeleteParentDir(string remotePath)
        //{
        //    remotePath = Path.GetDirectoryName(remotePath).Replace("\\", "/");

        //    //如果为空目录且非根目录则删除
        //    if (_Sftp.IsEmptyDirectory(remotePath) && !_RootPath.StartsWith(remotePath))
        //    {
        //        if (_Sftp.Delete(remotePath))
        //        {
        //            DeleteParentDir(remotePath);
        //        }
        //    }
        //}

        #endregion

        #region 升级固件
        public void UpgradeProgram(string programFile, Action<UpgradeProgramState> progress)
        {
            try
            {
                //string rootPath = _RootPath.Replace("pi", "Jakey");

                string name = "FC.Hidan";

                #region 停止旧版程序运行
                progress.Invoke(UpgradeProgramState.CloseTunningProgramStart);
                if (_Sftp.CreateFile(_RootPath + "stop"))
                {
                    System.Threading.Thread.Sleep(1500);

                    #region 判断stop是否执行成功
                    if (!_Sftp.IsExists(_RootPath + "stop"))
                    {
                        progress.Invoke(UpgradeProgramState.CloseTunningProgramSuccess);
                    }
                    else
                    {
                        progress.Invoke(UpgradeProgramState.CloseTunningProgramFail);
                    }
                    #endregion

                }
                else
                {
                    progress.Invoke(UpgradeProgramState.CloseTunningProgramFail);
                    return;
                }
                #endregion

                #region 删除旧版程序
                progress.Invoke(UpgradeProgramState.CleanProgramStart);
                if (_Sftp.DeleteDirectory(_RootPath + name))
                {
                    progress.Invoke(UpgradeProgramState.CleanProgramSuccess);
                }
                else
                {
                    progress.Invoke(UpgradeProgramState.CleanProgramFail);
                    return;
                }
                #endregion

                #region 解压新版程序文件
                string extractPath = this.GetBaseDirectory() + "Temp\\PIPrograms\\";
                progress.Invoke(UpgradeProgramState.DecompressionProgramStart);
                Bandit.Zip.ZipHelper.Extract(programFile, extractPath);
                progress.Invoke(UpgradeProgramState.DecompressionProgramSuccess);
                #endregion

                #region 上传新版程序文件到Tetra
                progress.Invoke(UpgradeProgramState.UpgradeProgramStart);
                if (_Sftp.UploadDirectory(extractPath + name, _RootPath + name))
                {
                    progress.Invoke(UpgradeProgramState.UpgradeProgramSuccess);
                }
                else
                {
                    progress.Invoke(UpgradeProgramState.UpgradeProgramFail);
                    return;
                }
                #endregion

                #region 重启系统
                progress.Invoke(UpgradeProgramState.LaunchNewProgramStart);
                if (_Sftp.CreateFile(_RootPath + "start"))
                {
                    progress.Invoke(UpgradeProgramState.LaunchNewProgramSuccess);
                }
                else
                {
                    progress.Invoke(UpgradeProgramState.LaunchNewProgramFail);
                    return;
                }
                #endregion

                progress.Invoke(UpgradeProgramState.UpgradeComplete);
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex, "UpgradeProgram");
                progress.Invoke(UpgradeProgramState.UpgradeFail);
            }
        }
        #endregion

        #region 上穿配置文件
        public bool UpdateConfigFile(string localPath, string subDirectory)
        {
            if (!File.Exists(localPath))
            {
                return false;
            }

            string remotePath = "/home/pi/Desktop/" + subDirectory + "/" + Path.GetFileName(localPath);

            return _Sftp.UploadFile(localPath, remotePath);
        }

        #endregion

        #region 删除配置文件
        public bool RemoveConfigFile(string deletePathFileName, string subDirectory)
        {
            string remotePath = "/home/pi/Desktop/" + subDirectory + "/" + Path.GetFileName(deletePathFileName);

            if (!_Sftp.IsExists(remotePath))
            {
                return false;
            }

            return _Sftp.Delete(remotePath);
        }

        #endregion

        /// <summary>
        /// 动态IP、静态IP切换
        /// </summary>
        /// <param name="isDHCP"></param>
        /// <returns></returns>
        public bool SwitchIPGetWay(bool isDHCP)
        {
            bool result = false;

            string rootPath = _RootPath.Replace("PI", "Jakey");

            string remotePath = rootPath + (isDHCP ? "dhcp" : "static");

            if (_Sftp.CreateFile(remotePath))
            {
                System.Threading.Thread.Sleep(1500);

                if (!_Sftp.IsExists(remotePath))
                {
                    result = _Sftp.CreateFile(rootPath + "start");
                }
            }

            return result;
        }

        public bool ChangeIP(string ipFile)
        {
            string rootPath = _RootPath.Replace("PI", "Jakey");

            string remotePath = rootPath + "interfaces.d/static/interfaces";

            return _Sftp.UploadFile(ipFile, remotePath);
        }

        private bool UploadFile(string relativePath)
        {
            string localPath = string.Format("{0}{1}", this.GetBaseDirectory(), relativePath);
            string remotePath = string.Format("{0}{1}", _RootPath, relativePath).Replace("\\", "/");

            return _Sftp.UploadFile(localPath, remotePath);
        }

        private bool DownloadFile(string relativePath, string localPath = null)
        {
            if (localPath == null)
            {
                localPath = string.Format("{0}{1}", this.GetBaseDirectory(), relativePath);
            }

            string remotePath = string.Format("{0}{1}", _RootPath, relativePath).Replace("\\", "/");

            return _Sftp.DownloadFile(remotePath, localPath);
        }

        public List<ConfigFileModel> GetRemoteConfigFile(string subDirectory, string FileExtension)
        {
            List<ConfigFileModel> configFileModels = new List<ConfigFileModel>();

            string remotePath = "/home/pi/Desktop/" + subDirectory;

            List<string> fileNames = _Sftp.GetFiles(remotePath);

            foreach (string filename in fileNames)
            {
                if (Path.GetExtension(filename) == FileExtension)
                {
                    ConfigFileModel configFileModel = new ConfigFileModel();

                    configFileModel.Name = Path.GetFileNameWithoutExtension(filename);

                    configFileModel.FileName = filename;

                    configFileModels.Add(configFileModel);
                }
            }

            return configFileModels;
        }

        public ObservableCollection<TetraTestLogModel> GetRemoteTestLogFile(string subDirectory)
        {
            ObservableCollection<TetraTestLogModel> configFileModels = new ObservableCollection<TetraTestLogModel>();

            string remotePath = "/home/pi/Desktop/" + subDirectory;

            if (_Sftp.IsExists(remotePath))
            {
                List<string> fileNames = _Sftp.GetFiles(remotePath);

                foreach (string filename in fileNames)
                {
                    if (!(Path.GetFileNameWithoutExtension(filename) == "" || Path.GetFileNameWithoutExtension(filename) == "."))
                    {
                        TetraTestLogModel tetraTestLogModel = new TetraTestLogModel();

                        tetraTestLogModel.Name = Path.GetFileNameWithoutExtension(filename);

                        tetraTestLogModel.FileName = filename;

                        tetraTestLogModel.IsDownLoad = true;

                        if (Path.GetExtension(filename).Contains("."))
                        {
                            tetraTestLogModel.IsFile = true;
                        }
                        else
                        {
                            tetraTestLogModel.IsFile = false;
                        }

                        configFileModels.Add(tetraTestLogModel);
                    }
                }
            }
            return configFileModels;
        }

        public bool DownloadLog(string localPath, string flag)
        {
            if (!Directory.Exists(localPath))
            {
                Directory.CreateDirectory(localPath);
            }

            string remotePath = "/home/pi/Desktop/" + flag;
            if (_Sftp.IsExists(remotePath))
            {
                return _Sftp.DownloadDirectory(remotePath, localPath);
            }
            else
            {
                return false;
            }
        }

        public bool DownloadTestLogDirectory(string localPath, string remotePath)
        {
            if (!Directory.Exists(localPath))
            {
                Directory.CreateDirectory(localPath);
            }

            //string remotePath = "/home/pi/Desktop/" + flag;
            if (_Sftp.IsExists(remotePath))
            {
                return _Sftp.DownloadDirectory(remotePath, localPath);
            }
            else
            {
                return false;
            }
        }

        public bool DownloadTestLogFile(string localPath, string remotePath)
        {
            //if (!Directory.Exists(localPath))
            //{
            //    Directory.CreateDirectory(localPath);
            //}

            //string remotePath = "/home/pi/Desktop/" + flag;

            return _Sftp.DownloadFile(remotePath, localPath);
        }

        public bool DeleteTestLogFile(string deletePathFileName)
        {
            string remotePath = deletePathFileName;//"/home/pi/Desktop/" + subDirectory + "/" + Path.GetFileName(deletePathFileName);

            if (!_Sftp.IsExists(remotePath))
            {
                return false;
            }

            return _Sftp.Delete(remotePath);
        }
        public bool DeleteTestLogDirectory()
        {
            string remotePath = "/home/pi/Desktop/" + "TestLog" + "/" ;

            if (!_Sftp.IsExists(remotePath))
            {
                return false;
            }



            return _Sftp.DeleteDirectory(remotePath);
        }
        public bool DeleteLogDirectory()
        {
            string remotePath = "/home/pi/Desktop/" + "Log" + "/";

            if (!_Sftp.IsExists(remotePath))
            {
                return false;
            }

            return _Sftp.DeleteDirectory(remotePath);
        }
        public bool SaveAndUpdateDB()
        {
            string localPath = "".GetBaseDirectory() + "db.json";
            string remotePath = string.Format("{0}db.json", _RootPath).Replace("\\", "/");

            return _Sftp.UploadFile(localPath, remotePath);
        }
    }
    public enum ResultState
    {
        /// <summary>
        /// 没有错误,表示成功
        /// </summary>
        OK,
        /// <summary>
        /// 配置文件丢失
        /// </summary>
        ConfigFileMiss,
        /// <summary>
        /// 上传视频文件失败
        /// </summary>
        UploadVideoFileFail,
        /// <summary>
        /// 上传EDID文件失败
        /// </summary>
        UploadEDIDFileFail,
        /// <summary>
        /// 上传Pattern文件失败
        /// </summary>
        UploadPatternFileFail,
        /// <summary>
        /// 上传配置文件失败
        /// </summary>
        UploadConfigFileFail,
        /// <summary>
        /// 上传配置失败
        /// </summary>
        UploadConfigFail,
        /// <summary>
        /// 连接服务器失败
        /// </summary>
        ConnectServerFail,
        /// <summary>
        /// 下载配置失败
        /// </summary>
        DownloadConfigFail,
        /// <summary>
        /// 下载配置文件失败
        /// </summary>
        DownloadConfigFileFail,
        /// <summary>
        /// 下载视频文件失败
        /// </summary>
        DownloadVideoFileFail,
        /// <summary>
        /// 下载EDID文件失败
        /// </summary>
        DownloadEDIDFileFail,
        /// <summary>
        /// 下载Pattern文件失败
        /// </summary>
        DownloadPatternFileFail
    }
    public enum UpgradeProgramState
    {
        CloseTunningProgramStart,
        CloseTunningProgramSuccess,
        CloseTunningProgramFail,
        CleanProgramStart,
        CleanProgramSuccess,
        CleanProgramFail,
        DecompressionProgramStart,
        DecompressionProgramSuccess,
        DecompressionProgramFail,
        UpgradeProgramStart,
        UpgradeProgramSuccess,
        UpgradeProgramFail,
        LaunchNewProgramStart,
        LaunchNewProgramSuccess,
        LaunchNewProgramFail,
        UpgradeComplete,
        UpgradeFail
    }
}
